home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** Program: MacShell
- ** File: window.c
- ** Written by: Eric Soldan
- **
- ** Copyright © 1990-1991 Apple Computer, Inc.
- ** All rights reserved.
- */
-
-
-
- /*****************************************************************************/
-
-
-
- #include "MacShell.h" /* Get the MacShell includes/typedefs, etc. */
- #include "MacShellCommon.h" /* Get the stuff in common with rez. */
- #include "MacShell.protos" /* Get the prototypes for MacShell. */
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef THINK_C
- #ifndef __SYSEQU__
- #include <SysEqu.h>
- #endif
- #endif
-
- #ifdef THINK_C
- #include "Utilities.h"
- #else
- #ifndef __UTILITIES__
- #include <Utilities.h>
- #endif
- #endif
-
-
-
- /*****************************************************************************/
-
-
-
- static RgnHandle gKeepUpdateRgn;
- static WindowPtr gOldPort;
-
- extern short gPrintPage; /* Non-zero means we are printing. */
-
-
-
- /*****************************************************************************/
- /*****************************************************************************/
-
-
-
- /* This function creates a new application window. An application window
- ** contains a document which is referenced by a handle in the refCon field.
- */
-
- #pragma segment Window
- OSErr DoNewWindow(FileRecHndl frHndl, WindowPtr *retWindow, WindowPtr behind, short attributes)
- {
- WindowPtr oldPort, window;
- ControlHandle ctl;
- Rect ctlRect;
- short h, v;
- OSErr err;
-
- if (!frHndl) return(noErr);
-
- /* We will allocate our own window storage instead of letting the Window
- ** Manager do it because GetNewWindow may load in temp. resources before
- ** making the NewPtr call, and this can lead to heap fragmentation.
- */
-
- GetPort(&oldPort);
-
- err = noErr;
-
- if (window = GetStaggeredWindow(rWindow, nil, FrontWindow(), behind, true)) {
- SetPort(window);
- SetWRefCon(window, (long)frHndl);
- NewWindowTitle(window);
-
- (*frHndl)->fileState.window = window;
- (*frHndl)->fileState.attributes = attributes;
- (*frHndl)->fileState.vScroll = nil;
- (*frHndl)->fileState.hScroll = nil;
-
- (*frHndl)->fileState.hArrowVal = 16; /* Default arrow value is 16. */
- (*frHndl)->fileState.vArrowVal = 16;
-
- h = window->portRect.right; /* Default document size is */
- if (attributes & kwHScroll) h -= 15; /* content less scrollbars. */
- (*frHndl)->fileState.hDocSize = h; /* We don't have to initialize the page */
- v = window->portRect.bottom; /* values since the scrollbars won't be */
- if (attributes & kwVScroll) v -= 15; /* active until the window is resized */
- (*frHndl)->fileState.vDocSize = v; /* or these values are set elsewhere. */
-
- if (attributes & kwHScroll) { /* Caller wants a horizontal scrollbar... */
- ctlRect = window->portRect;
- --ctlRect.left;
- ++ctlRect.right;
- ctlRect.top = ++ctlRect.bottom - 16;
- if (attributes & (kwHScrollLessGrow - kwHScroll + kwGrowIcon)) ctlRect.right -= 15;
- OffsetRect(&ctlRect, 0, -16384);
- ctl = NewControl(window, &ctlRect, nil, true, 0, 0, 0, scrollBarProc, 0L);
- if (ctl)
- (*frHndl)->fileState.hScroll = ctl;
- else
- err = memFullErr;
- }
-
- if (!err) {
- if (attributes & kwVScroll) { /* Caller wants a vertical scrollbar... */
- ctlRect = window->portRect;
- --ctlRect.top;
- ++ctlRect.bottom;
- ctlRect.left = ++ctlRect.right - 16;
- if (attributes & (kwVScrollLessGrow - kwVScroll + kwGrowIcon)) ctlRect.bottom -= 15;
- OffsetRect(&ctlRect, 0, -16384);
- ctl = NewControl(window, &ctlRect, nil, true, 0, 0, 0, scrollBarProc, 0L);
- if (ctl)
- (*frHndl)->fileState.vScroll = ctl;
- else
- err = memFullErr;
- }
- }
-
- if (!err) {
- err = (*((*frHndl)->fileState.initContentProc))(frHndl, window);
- if (!err) {
- if (gPrintPage)
- MoveWindow(window, 16384, 16384, true);
- /* So the window can be hidden while printing, yet
- ** PrintMonitor can get the document name. */
- ShowWindow(window);
- if (gPrintPage)
- MoveWindow(window, 16384, 16384, true);
- /* Moving invisible windows to the front doesn't always
- ** get them to the front. Now that it is visible, moving
- ** it will definitely get it to the front. */
- }
- }
- else DisposeAnyWindow(window);
- }
- else err = memFullErr;
-
- SetPort(oldPort);
- if (retWindow) *retWindow = window;
-
- return(err);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This function updates the window title to reflect the new document name.
- ** The new document name is stored in the fileState portion of the document.
- ** This is automatically set to 'Untitled # N' for new documents, and is
- ** updated when a user does a save-as.
- */
-
- #pragma segment Window
- void NewWindowTitle(WindowPtr window)
- {
- FileRecHndl frHndl;
- Str255 wTitle;
-
- if (window) {
- if (frHndl = (FileRecHndl)GetWRefCon(window)) {
- pstrcpy((char *)wTitle, (char *)(*frHndl)->fileState.fss.name);
- SetWTitle(window, wTitle);
- }
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This function returns the state of the window's document. If the document
- ** is dirty, then true is returned. If the document is clean, or the window
- ** has no document, then false is returned.
- */
-
- #pragma segment Window
- Boolean GetWindowDirty(WindowPtr window)
- {
- FileRecHndl frHndl;
-
- if (IsAppWindow(window))
- if (frHndl = (FileRecHndl)GetWRefCon(window))
- return((*frHndl)->fileState.docDirty);
-
- return(false);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This function sets the state of the window's document. */
-
- #pragma segment Window
- void SetWindowDirty(WindowPtr window)
- {
- FileRecHndl frHndl;
-
- if (IsAppWindow(window))
- if (frHndl = (FileRecHndl)GetWRefCon(window))
- (*frHndl)->fileState.docDirty = true;
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* Close all the windows. This is called prior to quitting the application.
- ** This function returns true if all windows were closed. The user may decide
- ** to abort a save, thus stopping the closing of the windows. If the user
- ** does this, false will be returned, indicating that all windows were not
- ** closed after all.
- */
-
- #pragma segment Window
- Boolean DisposeAllWindows(void)
- {
- WindowPtr window;
-
- #ifdef __SYSEQU__
- while (window = *(WindowPtr *)WindowList) {
- #else
- while (window = (WindowPtr)WindowList) {
- #endif
- /* While we have a front window, try closing it. */
-
- if (!DisposeOneWindow(window, iQuit)) return(false);
- /* When DisposeOneWindow returns false, this means that the window
- ** didn't close. The only cause of this is if the window had a
- ** document that needed saving, and the user cancelled the save.
- ** If the window succeeded in getting closed, then we are
- ** returned true. Either way, we return the result.
- */
- }
-
- return(true);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* Closes one window. This window may be an application window, or it may be
- ** a system window. If it is an application window, it may have a document
- ** that needs saving.
- */
-
- #pragma segment Window
- Boolean DisposeOneWindow(WindowPtr window, short saveMode)
- {
- FileRecHndl frHndl;
- OSErr err;
-
- if (window) {
- if (IsAppWindow(window)) {
- /* First, if the window is an application window, try saving
- ** the document. Remember that the user may cancel the save.
- */
-
- if (frHndl = (FileRecHndl)GetWRefCon(window)) {
-
- err = AppSaveDocument(frHndl, window, saveMode);
- if (err) {
- if (err != userCanceledErr)
- Alert(rErrorAlert, (ModalFilterProcPtr)alertFilter);
- return(false);
- } /* Stop closing windows on error or user cancel. */
-
- SendMessage(frHndl, kDisconnectMssg);
- AppDisposeDocument(frHndl);
- /* The document is saved, or the user doesn't care about
- ** that document, so dispose of the document.
- */
- }
- }
- DisposeAnyWindow(window);
- }
-
- return(true);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- WindowPtr SetFilePort(FileRecHndl frHndl)
- {
- WindowPtr oldPort;
-
- GetPort(&oldPort);
- if (frHndl) SetPort((*frHndl)->fileState.window);
- return(oldPort);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void DoResizeWindow(WindowPtr window, short oldh, short oldv)
- {
- FileRecHndl frHndl;
- WindowPtr oldPort;
- short attributes;
- Boolean growIconSpace;
- Rect portRct, rct;
- ControlHandle hScroll, vScroll;
- RgnHandle updateRgn;
-
- if (!window) return;
-
- frHndl = (FileRecHndl)GetWRefCon(window);
- oldPort = SetFilePort(frHndl);
- attributes = (*frHndl)->fileState.attributes;
- growIconSpace = (attributes & (kwGrowIcon | (kwHScrollLessGrow - kwHScroll) | (kwVScrollLessGrow - kwVScroll)));
- /* growIconSpace true if window has grow icon or a blank space for one. */
-
- SetOrigin(0, 0);
- portRct = window->portRect;
-
- if (growIconSpace) {
- rct.left = (rct.right = oldh) - 15;
- rct.top = (rct.bottom = oldv) - 15;
- EraseRect(&rct);
- InvalRect(&rct);
- rct = portRct;
- rct.left = rct.right - 15;
- rct.top = rct.bottom - 15;
- EraseRect(&rct);
- }
-
- SetOrigin(0, -16384);
- if (hScroll = (*frHndl)->fileState.hScroll) {
- HideControl(hScroll);
- rct = (*hScroll)->contrlRect;
- MoveControl(hScroll, rct.left, portRct.bottom - 15 - 16384);
- SizeControl(hScroll, rct.right - rct.left + (portRct.right - portRct.left - oldh), 16);
- }
- if (vScroll = (*frHndl)->fileState.vScroll) {
- HideControl(vScroll);
- rct = (*vScroll)->contrlRect;
- MoveControl(vScroll, portRct.right - 15, rct.top);
- SizeControl(vScroll, 16, rct.bottom - rct.top + (portRct.bottom - portRct.top - oldv));
- }
-
- AdjustScrollBars(window);
-
- if (hScroll) ShowControl(hScroll);
- if (vScroll) ShowControl(vScroll);
-
- SetOrigin(0, 0);
- if (attributes & kwGrowIcon) DoDrawGrowIcon(window, false, false);
-
- BeginContent(window);
- (*((*frHndl)->fileState.resizeContentProc))(window, oldh, oldv);
- updateRgn = NewRgn();
- CopyRgn(((WindowPeek)window)->updateRgn, updateRgn);
- EndContent(window);
- UnionRgn(updateRgn, ((WindowPeek)window)->updateRgn, ((WindowPeek)window)->updateRgn);
- DisposeRgn(updateRgn);
-
- SetPort(oldPort);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void DoDrawFrame(WindowPtr window)
- {
- FileRecHndl frHndl;
- WindowPtr oldPort;
- short attributes;
- Rect portRect;
-
- if (window) {
-
- frHndl = (FileRecHndl)GetWRefCon(window);
- oldPort = SetFilePort(frHndl);
- SetOrigin(0, 0);
- portRect = window->portRect;
-
- attributes = (*frHndl)->fileState.attributes;
- if (attributes & kwGrowIcon) DoDrawGrowIcon(window, false, false);
-
- SetOrigin(0, -16384);
- DoDrawControls(window, true);
- SetOrigin(0, 0);
- (*((*frHndl)->fileState.drawFrameProc))(frHndl, window);
-
- SetPort(oldPort);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- RgnHandle DoCalcFrameRgn(WindowPtr window)
- {
- FileRecHndl frHndl;
- WindowPtr oldPort;
- RgnHandle urgn, wrgn;
- short attributes, i;
- Boolean growIconSpace;
- Rect portRect, rct;
- Point l2g;
- ControlHandle ctl;
-
- urgn = NewRgn();
- if (!window) return(urgn);
-
- frHndl = (FileRecHndl)GetWRefCon(window);
- oldPort = SetFilePort(frHndl);
- SetOrigin(0, 0);
-
- (*((*frHndl)->fileState.calcFrameRgnProc))(frHndl, window, urgn);
-
- portRect = window->portRect;
- attributes = (*frHndl)->fileState.attributes;
- growIconSpace = (attributes & (kwGrowIcon | (kwHScrollLessGrow - kwHScroll) | (kwVScrollLessGrow - kwVScroll)));
- /* growIconSpace true if window has grow icon or a blank space for one. */
-
- wrgn = NewRgn();
-
- if (growIconSpace) {
- rct = portRect;
- rct.left = rct.right - 15;
- rct.top = rct.bottom - 15;
- RectRgn(urgn, &rct);
- }
-
- for (i = 0; i < 2; ++i) {
- ctl = (i) ? (*frHndl)->fileState.vScroll : (*frHndl)->fileState.hScroll;
- if (ctl) {
- rct = (*ctl)->contrlRect;
- OffsetRect(&rct, 0, 16384);
- RectRgn(wrgn, &rct);
- UnionRgn(urgn, wrgn, urgn);
- }
- }
-
- l2g.h = l2g.v = 0;
- LocalToGlobal(&l2g);
- OffsetRgn(urgn, l2g.h, l2g.v);
- DisposeRgn(wrgn);
-
- SetPort(oldPort);
- return(urgn);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void DoUpdateSeparate(WindowPtr window, RgnHandle *contRgn, RgnHandle *frameRgn)
- {
- RgnHandle urgn, wrgn;
-
- *contRgn = *frameRgn = nil;
- if (!window) return;
-
- urgn = DoCalcFrameRgn(window);
- wrgn = NewRgn();
-
- DiffRgn(((WindowPeek)window)->updateRgn, urgn, wrgn);
- if (!EmptyRgn(wrgn)) {
- *contRgn = wrgn;
- wrgn = NewRgn();
- }
- SectRgn(((WindowPeek)window)->updateRgn, urgn, wrgn);
-
- if (!EmptyRgn(wrgn)) *frameRgn = wrgn;
- else DisposeRgn(wrgn);
-
- DisposeRgn(urgn);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void BeginContent(WindowPtr window)
- {
- RgnHandle updateRgn, frameRgn;
- Point contOrg;
-
- GetPort(&gOldPort);
-
- if (window) {
- SetPort(window);
- CopyRgn(updateRgn = ((WindowPeek)window)->updateRgn, gKeepUpdateRgn = NewRgn());
- frameRgn = DoCalcFrameRgn(window);
- DiffRgn(((WindowPeek)window)->contRgn, frameRgn, updateRgn);
- DisposeRgn(frameRgn);
- BeginUpdate(window);
- GetContentOrigin(window, &contOrg);
- SetOrigin(contOrg.h, contOrg.v);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void EndContent(WindowPtr window)
- {
- if (window) {
- EndUpdate(window);
- CopyRgn(gKeepUpdateRgn, ((WindowPeek)window)->updateRgn);
- SetOrigin(0, 0);
- DisposeRgn(gKeepUpdateRgn);
- }
- SetPort(gOldPort);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void AdjustScrollBars(WindowPtr window)
- {
- FileRecHndl frHndl;
- WindowPtr oldPort;
- ControlHandle hScroll, vScroll;
- Rect portRct;
- short h, v, maxVal, val;
-
- if (!window) return;
-
- oldPort = SetFilePort(frHndl = (FileRecHndl)GetWRefCon(window));
- portRct = window->portRect;
- hScroll = (*frHndl)->fileState.hScroll;
- vScroll = (*frHndl)->fileState.vScroll;
-
- SetOrigin(0, -16384);
-
- h = portRct.right - portRct.left;
- if (vScroll) h -= 15;
- maxVal = (*frHndl)->fileState.hDocSize - h;
- if (hScroll) {
- if (maxVal < (val = GetCtlValue(hScroll))) maxVal = val;
- SetCtlMax(hScroll, maxVal);
- }
- h -= (val = (*frHndl)->fileState.hArrowVal);
- if (h < val) h = val;
- (*frHndl)->fileState.hPageVal = h;
-
- v = portRct.bottom - portRct.top;
- if (hScroll) v -= 15;
- maxVal = (*frHndl)->fileState.vDocSize - v;
- if (vScroll) {
- if (maxVal < (val = GetCtlValue(vScroll))) maxVal = val;
- SetCtlMax(vScroll, maxVal);
- }
- v -= (val = (*frHndl)->fileState.vArrowVal);
- if (v < val) v = val;
- (*frHndl)->fileState.vPageVal = v;
-
- SetOrigin(portRct.left, portRct.top);
- SetPort(oldPort);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void GetContentOrigin(WindowPtr window, Point *contOrg)
- {
- FileRecHndl frHndl;
- ControlHandle ctl;
-
- contOrg->h = contOrg->v = 0;
-
- if (window) {
- frHndl = (FileRecHndl)GetWRefCon(window);
- if (ctl = (*frHndl)->fileState.hScroll) contOrg->h = GetCtlValue(ctl);
- if (ctl = (*frHndl)->fileState.vScroll) contOrg->v = GetCtlValue(ctl);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void SetContentOrigin(WindowPtr window, short newh, short newv)
- {
- FileRecHndl frHndl;
- WindowPtr oldPort;
- ControlHandle hScroll, vScroll;
- short max, dh, dv;
- Point old;
- Rect portRct;
- RgnHandle updateRgn;
-
- if (!window) return;
-
- oldPort = SetFilePort(frHndl = (FileRecHndl)GetWRefCon(window));
- hScroll = (*frHndl)->fileState.hScroll;
- vScroll = (*frHndl)->fileState.vScroll;
- GetContentOrigin(window, &old);
-
- SetOrigin(0, -16384);
- if (hScroll) {
- if (newh < 0) newh = 0;
- if (newh > (max = GetCtlMax(hScroll))) newh = max;
- SetCtlValue(hScroll, newh);
- }
- if (vScroll) {
- if (newv < 0) newv = 0;
- if (newv > (max = GetCtlMax(vScroll))) newv = max;
- SetCtlValue(vScroll, newv);
- }
- dh = old.h - newh;
- dv = old.v - newv;
-
- BeginContent(window);
- portRct = window->portRect;
- ScrollRect(&portRct, dh, dv, updateRgn = NewRgn());
- EndContent(window);
- SetOrigin(portRct.left, portRct.top);
-
- /* We want to add the scrolled-in area into the updateRgn. We
- ** also want to keep the old area. The old update area is
- ** no longer mapped to the same location, due to the scroll,
- ** so offset it by the amount scrolled. Once it is offset, we
- ** can add our new update portion to the updateRgn. */
- OffsetRgn(((WindowPeek)window)->updateRgn, dh, dv);
- InvalRgn(updateRgn);
- DisposeRgn(updateRgn);
-
- SetPort(oldPort); /* Put things back the way we found them. */
- DoCursor(); /* Cursor region may be invalid due to
- ** content being scrolled. Force it to
- ** be recalculated. */
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void GetContentRect(WindowPtr window, Rect *contRct)
- {
- FileRecHndl frHndl;
- ControlHandle ctl;
-
- SetRect(contRct, 0, 0, 0, 0);
-
- if (window) {
- frHndl = (FileRecHndl)GetWRefCon(window);
- *contRct = window->portRect;
- if (ctl = (*frHndl)->fileState.hScroll) contRct->bottom -= 15;
- if (ctl = (*frHndl)->fileState.vScroll) contRct->right -= 15;
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void SetDocSize(FileRecHndl frHndl, short hSize, short vSize)
- {
- if (frHndl) {
- (*frHndl)->fileState.hDocSize = hSize;
- (*frHndl)->fileState.vDocSize = vSize;
- AdjustScrollBars((*frHndl)->fileState.window);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void DoImageDocument(FileRecHndl frHndl)
- {
- (*((*frHndl)->fileState.imageProc))(frHndl);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void DoContentClick(WindowPtr window, EventRecord *event)
- {
- FileRecHndl frHndl;
-
- if (IsAppWindow(window))
- if (frHndl = (FileRecHndl)GetWRefCon(window))
- (*((*frHndl)->fileState.contentClickProc))(window, event);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Window
- void DoContentKey(WindowPtr window, EventRecord *event)
- {
- FileRecHndl frHndl;
-
- if (IsAppWindow(window))
- if (frHndl = (FileRecHndl)GetWRefCon(window))
- (*((*frHndl)->fileState.contentKeyProc))(window, event);
- }
-
-
-
-